#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <atomic>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <boost/algorithm/string.hpp>

using namespace std;

namespace ns_commfunc
{
    const string temp = "./temp/";

    // 将文件名变为文件路径，并且添加后缀
    class PathUtil
    {

    public: 
        static string AddSuffix(const string filename, const string suffix)
        {
            string ret = temp + filename + suffix;
            return ret;
        }

        //编译模块
        static string filepath_src(const string& filename)
        {
            return AddSuffix(filename, ".cpp");
        }

        static string filepath_exe(const string& filename)
        {
            return AddSuffix(filename, ".exe");
        }

        static string filepath_stderr(const string& filename)
        {
            return AddSuffix(filename, ".compile_err");
        }

        //运行模块
         static string filepath_stdin(const string& filename)
        {
            return AddSuffix(filename, ".stdin");
        }

        static string filepath_stdout(const string& filename)
        {
            return AddSuffix(filename, ".stdout");
        }

        static string filepath_stderr_runner(const string& filename)
        {
            return AddSuffix(filename, ".stderr");
        }

    
    };

    class TimeUtil
    {
    public:
        static string Gettimeofms()
        {
            struct timeval tv;
            gettimeofday(&tv, nullptr);
            string ret = to_string(tv.tv_sec * 1000 + tv.tv_usec / 1000);

            return ret;
        }
    };

    class FileUtil
    {
    public:

        static bool Isexist_file(const string filename)
        {
            struct stat temp;
            int ret = stat(filename.c_str(), &temp);

            return ret == 0 ? true : false;
        }

        static string UniqueFilename()
        {
            static atomic_uint id(0);
            id++;

            return TimeUtil::Gettimeofms() + "_" + to_string(id);
        }

        static bool WritecodeToFile(const string filename, const string& content)
        {
            ofstream out(filename);
            if(!out.is_open()) return false;

            out.write(content.c_str(), content.size());
            out.close();

            return true;
        }

        static bool Readfile(const string& filename, string& content, bool keep)
        {
            
            ifstream in(filename);
            if(!in.is_open()) return false;
            string line;
            while(getline(in, line))
            {
                content += line;
                content += keep ? "\n" : "";
            }

            in.close();

            return true;
        }

        static string CodeTodesc(int status, string filename)
        {
            string ret = "";

            switch (status)
            {
            case 0:
                ret = "运行正常";
                break;
            case -1:
                ret = "代码为空";
                break;
            case -2:
                ret = "未知错误";
                break;
            case -3:
                // ret = "编译错误";
                FileUtil::Readfile(PathUtil::filepath_stderr(filename), ret, true);
                break;
            case 24:
                ret = "超时";
		break;
            default:
                ret = "待填充";
                break;
            }

            return ret;
        }


    };

    class StringUtil
    {
        public:
        static void SplitStr(const string& in, vector<string>& vs, const string& sep)
        {
            //最后一个参数：压缩连续分隔符sep
            boost::split(vs, in, boost::is_any_of(sep), boost::algorithm::token_compress_on);
        }

    };
}
